//You are given an array prices where prices[i] is the price of a given stock 
//on the iᵗʰ day. 
//
// Find the maximum profit you can achieve. You may complete as many 
//transactions as you like (i.e., buy one and sell one share of the stock multiple times) 
//with the following restrictions: 
//
// 
// After you sell your stock, you cannot buy stock on the next day (i.e., 
//cooldown one day). 
// 
//
// Note: You may not engage in multiple transactions simultaneously (i.e., you 
//must sell the stock before you buy again). 
//
// 
// Example 1: 
//
// 
//Input: prices = [1,2,3,0,2]
//Output: 3
//Explanation: transactions = [buy, sell, cooldown, buy, sell]
// 
//
// Example 2: 
//
// 
//Input: prices = [1]
//Output: 0
// 
//
// 
// Constraints: 
//
// 
// 1 <= prices.length <= 5000 
// 0 <= prices[i] <= 1000 
// 
// Related Topics 数组 动态规划 👍 952 👎 0

package leetcode.editor.cn;

import org.junit.Assert;

public class P309BestTimeToBuyAndSellStockWithCooldown {
    public static void main(String[] args) {
        Solution solution = new P309BestTimeToBuyAndSellStockWithCooldown().new Solution();
        Assert.assertEquals(solution.maxProfit(new int[]{1, 2, 3, 0, 2}), 3);
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        public int maxProfit(int[] prices) {
            int len = prices.length;
            int[][] state = new int[len][2];
            state[0][1] = -prices[0];
            state[0][0] = 0;
            for (int i = 1; i < len; i++) {
                if (i == 1) {
                    state[i][0] = Math.max(state[i - 1][1] + prices[i], state[i - 1][0]);
                    state[i][1] = Math.max(state[i - 1][0] - prices[i], state[i - 1][1]);
                } else {
                    state[i][0] = Math.max(state[i - 1][1] + prices[i], state[i - 1][0]);
                    state[i][1] = Math.max(state[i - 2][0] - prices[i], state[i - 1][1]);
                }
            }
            return state[len - 1][0];
        }

        public int maxProfit_with_cool(int[] prices) {
            int n = prices.length;
            int dp_i_0 = 0, dp_i_1 = Integer.MIN_VALUE;
            int dp_pre_0 = 0; // 代表 dp[i-2][0]
            for (int i = 0; i < n; i++) {
                int temp = dp_i_0;
                dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]);
                dp_i_1 = Math.max(dp_i_1, dp_pre_0 - prices[i]);
                dp_pre_0 = temp;
            }
            return dp_i_0;
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}